package com.fxu.gen;

import cn.hutool.core.util.StrUtil;
import com.fxu.framework.biz.base.Limits;
import com.fxu.framework.core.base.Constant;
import com.fxu.framework.core.enums.ShowStatus;
import com.fxu.framework.core.enums.ShowStrStatus;
import com.fxu.framework.core.enums.StatusEnum;
import com.fxu.framework.core.exception.MsgException;
import com.fxu.gen.enums.ClnType;
import com.fxu.gen.enums.FormType;
import com.fxu.gen.enums.TplEnum;
import com.fxu.tpl.entity.Column;
import com.fxu.tpl.entity.Link;
import com.fxu.tpl.entity.Table;
import com.fxu.tpl.enums.ColumnTypeEnum;

import java.io.File;
import java.util.Arrays;
import java.util.List;

/**
 * 基于uniapp-vue2
 * @author fangxu
 * @version 2024-06-29
 */
public final class UniappVue2 extends Base {
	public UniappVue2(Table table, File destFile) {
		super(table, TplEnum.VbenAdmin, destFile);
	}

	@Override
	public String doReplace() {
		String curdSchemas = getCrudSchemas(table, columns, 1);
		String moduleName = table.getModule().getName();
		if (moduleName.contains("/")) {
			moduleName = moduleName.substring(moduleName.indexOf("/") + 1);
		}

		// fileTxt = fileTxt.replace("name: 'HdbUser',", "name: '"+tableBean+"',");
		fileTxt = fileTxt.replace("const name = '角色'", "const name = '"+table.getCmmt()+"'");
		fileTxt = fileTxt.replace("const bean = 'sys.sysRole'", "const bean = '"+moduleName+"."+AutoUtil.firstLowerBean(tableBean)+"'");
		fileTxt = fileTxt.replace("const perms = getPerms('角色管理')", "const perms = getPerms('"+table.getCmmt()+"管理')");
		// fileTxt = fileTxt.replace("const priKey: string = 'id'", "const priKey: string = '"+ priKey +"'");
		fileTxt = fileTxt.replace("const apiParams: ApiParams = { showFlags: 'menuList[name]', params: {} }",
				"const apiParams: ApiParams = { " + getShowFlags() + "params: {"+(AutoUtil.hasColumn(columns, Constant.NEW_PARENT_ID) ? " pid: 0 " : "")+"} }");
		fileTxt = fillByKey(fileTxt, "CrudSchema[] = [", "  ] // schemas", curdSchemas);

		// 导入导出
		if (!isTrue(table.getIsExport())) {
			fileTxt = removeLine(fileTxt, 1, "import ExcelExport from '@/views/comp/ExcelExport.vue'");
			fileTxt = removeLine(fileTxt, 4, "<ExcelExport :disabled=\"!perms.export\"");
			fileTxt = removeLine(fileTxt, 3, "let resTotal = 0");
			fileTxt = fileTxt.replace(" @fetch-success=\"({ total }) => resTotal = total\"", "");
		}
		if (!isTrue(table.getIsImport())) {
			fileTxt = removeLine(fileTxt, 4, "<ExcelImport :disabled=\"!perms.import\"");
			fileTxt = removeLine(fileTxt, 1, "import ExcelImport from '@/views/comp/ExcelImport.vue'");
		}

		// 树形表格
		if (AutoUtil.hasColumn(columns, Constant.NEW_PARENT_ID)) {
			fileTxt = fileTxt.replace("...api.getTableProps(name, columns, 270)",
					"...api.getTableProps(name, columns, 270, true)");
		} else {
			// 默认不自动打开
			/*fileTxt = fileTxt.replace(", nextTick", "");
			fileTxt = fileTxt.replace(", expandAll", "");
			fileTxt = removeLine(fileTxt, 2, "if (total > 0) nextTick(expandAll)");*/
		}

		// 级联列表 一对多链接对象
		String innerSchemas = getCascadeSchemas(1);
		if (StrUtil.isNotEmpty(innerSchemas)) {
			fileTxt = fillByKey(fileTxt, "reactive<Cascade[]>([", "  ]) // inners", innerSchemas);
			fileTxt = fileTxt.replace("import {} from './data'", "import { " + getInnerSchemas() + " } from './data'");
		} else {
			fileTxt = fileTxt.replace(", Cascade", "");
			fileTxt = removeLine(fileTxt, 1, "// 级联对象定义");
			fileTxt = removeLine(fileTxt, 1, "const inners = reactive<Cascade[]>([");
			fileTxt = removeLine(fileTxt, 1, "]) // inners");
			fileTxt = removeLine(fileTxt, 5, "<a-button @click=\"openDetail(record)\" class=\"mr-1\">详情</a-button>");
			fileTxt = removeLine(fileTxt, 2, "<DetlModal :title=\"name\"");
			fileTxt = removeLine(fileTxt, 1, "import { DetlModal, useDtlModel } from '@/views/comp/detl'");
			fileTxt = removeLine(fileTxt, 1, "const [registerDetl, { openDetail, closeDetail }] = useDtlModel()");
			fileTxt = removeLine(fileTxt, 3, "closeDetail()");
			fileTxt = removeLine(fileTxt, 1, "import {} from './data'");
			fileTxt = fileTxt.replace(" :cascades=\"inners\"", "");
			fileTxt = fileTxt.replace(", reactive", "");
			fileTxt = fileTxt.replace(", columns, 270",", columns, 200");
		}

		// text字段展示
		String bigColumn = getBigColumn(2);
		if (StrUtil.isNotEmpty(bigColumn)) {
			fileTxt = fillByKey(fileTxt, "<template #expandedRowRender=\"{ record }\">",
					"      </template><!-- expanded -->", bigColumn);
		} else {
			int start = fileTxt.indexOf("      <template #expandedRowRender=\"{ record }\">");
			int end = fileTxt.indexOf("</template><!-- expanded -->\n") + "</template><!-- expanded -->\n".length();
			if (start > 0 && end > start) {
				fileTxt = fileTxt.substring(0, start) + fileTxt.substring(end);
			}
			// fileTxt = fileTxt.replace("width: 270,","width: 200,");
		}
		if (fileTxt.contains("return h(") || fileTxt.contains("=> h(")) {
			fileTxt = fileTxt.replace("{ ref", "{ ref, h");
		}
		// 需要增加的组件
		if (!fileTxt.contains("return h(TableImg,") && !fileTxt.contains("=> h(TableImg,")) {
			fileTxt = removeLine(fileTxt, 1, "import TableImg from '@/components/Table/src/components/TableImg.vue'");
		}
		// 需要增加的组件
		if (!fileTxt.contains("h(FileUpload,")) {
			fileTxt = removeLine(fileTxt, 1, "import FileUpload from '@/views/comp/upload/FileUpload.vue'");
		}
		// 需要增加的组件
		if (fileTxt.contains("return h(Tag,")) {
			String temp = "Tag";
			fileTxt = fileTxt.replace("import {} from 'ant-design-vue'",
					"import { " + temp + " } from 'ant-design-vue'");
		} else {
			fileTxt = removeLine(fileTxt, 1, "import {} from 'ant-design-vue'");
		}

		// 需要增加的组件
		if (fileTxt.contains("return h(Tinymce,")) {
			fileTxt = fileTxt.replace("// import { Tinymce } from '@/components/Tinymce/index'",
					"import { Tinymce } from '@/components/Tinymce/index'");
		} else {
			fileTxt = removeLine(fileTxt, 1, "// import { Tinymce } from '@/components/Tinymce/index'");
		}

		// 没有操作的页面
		if (!table.getHasAction()) {
			if (fileTxt.contains("inners")) {
				fileTxt = removeLine(fileTxt, 5, "<ActionButtons :deleted=\"perms.delete\"");
				fileTxt = removeLine(fileTxt, 5, "<a-button :disabled=\"!perms.edit\"");
			} else {
				int start = fileTxt.indexOf("      <template #bodyCell=\"{ column, record }\">");
				int end = fileTxt.indexOf("</template><!-- bodyCell -->\n") + "</template><!-- bodyCell -->\n".length();
				if (start > 0 && end > start) {
					fileTxt = fileTxt.substring(0, start) + fileTxt.substring(end);
				}
				/*start = fileTxt.indexOf("    actionColumn: {");
				end = fileTxt.indexOf("} // actionColumn\n") + "} // actionColumn\n".length();
				if (start > 0 && end > start) {
					fileTxt = fileTxt.substring(0, start) + fileTxt.substring(end);
				}*/
				fileTxt = removeLine(fileTxt, 2, "loading: loading");
				fileTxt = fileTxt.replace(", columns, 270",", columns, 0");
				fileTxt = fileTxt.replace(", columns, 200",", columns, 0");
			}
			fileTxt = removeLine(fileTxt, 4, "<a-button :disabled=\"!perms.add\"");
			fileTxt = removeLine(fileTxt, 2, "<SaveModal :title=\"name\" :schemas=\"forms\"");
			fileTxt = removeLine(fileTxt, 1, "import ActionButtons from '@/views/comp/ActionButtons.vue'");
			fileTxt = removeLine(fileTxt, 1, "import { SaveModal, useSaveModel } from '@/views/comp/save'");
			fileTxt = removeLine(fileTxt, 1, "const [registerSave,");
			fileTxt = removeLine(fileTxt, 1, "const loading = ref(false)");

			fileTxt = removeLine(fileTxt, 1, "// 对按钮权限控制");
			fileTxt = removeLine(fileTxt, 1, "const disBtns = [!perms.hide");
			fileTxt = fileTxt.replace("useCrud(schemas, disBtns)", "useCrud(schemas)");

			fileTxt = fileTxt.replace("const { forms, columns, statusOpts } = useCrud(schemas)",
					"const { columns } = useCrud(schemas)");

			int start = fileTxt.indexOf("  function handleOpen(record: any) {");
			int end = fileTxt.indexOf("</script>");
			if (start > 0 && end > start) {
				fileTxt = fileTxt.substring(0, start) + fileTxt.substring(end);
			}
		} else {
			fileTxt = fileTxt.replace("} // actionColumn", "}");
			fileTxt = fileTxt.replace("<!-- bodyCell -->", "");
		}

		if (!fileTxt.contains("= useModal()")) {
			fileTxt = removeLine(fileTxt, 1, "import { useModal } from '@/components/Modal'");
		}

		// 权限控制
		if (!isTrue(table.getIsPerm())) {
			fileTxt = removeLine(fileTxt, 1, "const perms = getPerms('");
			fileTxt = removeLine(fileTxt, 1, "// 对按钮权限控制");
			fileTxt = removeLine(fileTxt, 1, "const disBtns = [!perms.hide");
			fileTxt = fileTxt.replace("useCrud(schemas, disBtns)", "useCrud(schemas)");
			fileTxt = fileTxt.replace(", getPerms", "");
			fileTxt = fileTxt.replace(" :disabled=\"!perms.add\"", "");
			fileTxt = fileTxt.replace(" :disabled=\"!perms.import\"", "");
			fileTxt = fileTxt.replace(" :disabled=\"!perms.export\"", "");
			fileTxt = fileTxt.replace(" :disabled=\"!perms.edit\"", "");
			fileTxt = fileTxt.replace(" :deleted=\"perms.delete\"", "");
		}
		// 去掉多余换行
		fileTxt = fileTxt.replace("\n\n\n", "\n\n");
		return fileTxt;
	}

	// 级联对象
	private String getBigColumn(int tab) {
		StrBuf innerSchemas = new StrBuf(true);
		columns.stream().filter(cln -> ColumnTypeEnum.find(cln.getType()) == ColumnTypeEnum.Text
				|| ColumnTypeEnum.find(cln.getType()) == ColumnTypeEnum.Blob).forEach(cln -> {
			innerSchemas.append(tab + 2, "<div class=\"p-4 bg-white\"><b>{1}:</b>", cln.getCmmt());
			innerSchemas.append(tab + 3, "<div class=\"pt-2 mt-2\" style=\"border-top: solid #eee;\"" +
					" v-html=\"record.{1}\"></div>", AutoUtil.firstLowerBean(cln.getName()));
			innerSchemas.append(tab + 2, "</div>");
		});
		return innerSchemas.moveLast().toString();
	}

	// 级联对象
	private String getInnerSchemas() {
		StringBuilder buffer = new StringBuilder();
		for (Link link : links) {
			if (!(link.getLinkTable() != null && link.getLinkColumn() != null
					&& isTrue(link.getIsList()) && link.getLinkTable().getColumnList() != null)) {
				continue;
			}
			String linkTableName = getLinkPropName(link, true);
			if (buffer.length() == 0) {
				buffer.append(linkTableName).append("Schemas");
			} else {
				buffer.append(", ").append(linkTableName).append("Schemas");
			}
		}
		return buffer.toString();
	}

	// 级联对象
	private String getCascadeSchemas(int tab) {
		StrBuf innerSchemas = new StrBuf(true);
		for (Link link : links) {
			boolean isSave = isTrue(link.getLinkSave());
			if (!(link.getLinkTable() != null && link.getLinkColumn() != null
					&& isTrue(link.getIsList()) && link.getLinkTable().getColumnList() != null)) {
				continue;
			}
			String priKey = getPriKeyClnName(link.getLinkTable().getColumnList());
			String linkColumnName = AutoUtil.firstLowerBean(link.getLinkColumn().getName());

			String linkTableBean = AutoUtil.firstLowerBean(link.getLinkTable().getName());
			String moduleName = link.getLinkTable().getModule().getName();
			if (moduleName.contains("/")) {
				moduleName = moduleName.substring(moduleName.indexOf("/") + 1);
			}

			innerSchemas.append(tab + 1, "{");
			innerSchemas.append(tab + 2, "bean: '{1}.{2}',", moduleName, linkTableBean);
			innerSchemas.append(tab + 2, "label: '{1}列表',", link.getLinkTable().getCmmt());
			innerSchemas.append(tab + 2, "field: '{1}s',", getLinkPropName(link));
			innerSchemas.append(tab + 2, "priKey: '{1}',", priKey);
			innerSchemas.append(tab + 2, "lnkKey: '{1}',", linkColumnName);
			if (!isSave) innerSchemas.append(tab + 2, "noSave: true,");
			innerSchemas.append(tab + 2, "params: { showFlags: '', params: {} },", priKey);
			innerSchemas.append(tab + 2, "schemas: {1}Schemas", getLinkPropName(link, true));
			//innerSchemas.append(tab + 2, "datas: [],");
			/*innerSchemas.append(tab + 2, "columns: [");
			for (Column cln : link.getLinkTable().getColumnList()) {
				// 表格和输入都不显示不输出
				if ((!isTrue(cln.getFormShow()) && !isTrue(cln.getListShow()))
						|| priKey.equals(cln.getName()) || linkColumnName.equals(cln.getName())) {
					continue;
				}
				innerSchemas.append(tab + 3, "{");

				String form = getFormItem(table, cln, priKey, tab + 2, true, isSave);
				form = form.replace("component:", "editComponent:");
				form = form.replace("componentProps:", "editComponentProps:");
				form = form.replace("customRender:", "editRender:");
				innerSchemas.append(form + "\n");
				innerSchemas.append(tab + 3, "},");
			}
			innerSchemas.append(tab + 2, "],");*/
			innerSchemas.append(tab + 1, "},");
		}
		return innerSchemas.moveLast().toString();
	}

	// 获取查询表单
	private String getShowFlags() {
		StringBuilder builder = new StringBuilder();
		columns.stream().filter(cln -> cln.getLinkTable() != null && !Constant.NEW_TENANT_ID.equals(cln.getName())).forEach(cln -> {
			String name = cln.getName().replace("_ids", "_list").replace("_id", "");
			builder.append(",").append(AutoUtil.firstLowerBean(name)).append("[").append(cln.getLinkTable().getShowCln()).append("]");
		});
		/*for (Link link : links) {
			if (!(link.getLinkTable() != null && link.getLinkColumn() != null && isTrue(link.getLinkSave())
					&& isTrue(link.getIsList()) && link.getLinkTable().getColumnList() != null)) {
				continue;
			}
			String linkTableName = getLinkPropName(link);
			builder.append(",").append(linkTableName).append("List");
		}*/
		if (AutoUtil.hasColumn(columns, Constant.NEW_PARENT_ID)) {
			builder.append(",children");
		}
		List<String> specs = Arrays.asList(Constant.CLN_CREATE_BY, Constant.CLN_MODIFY_BY, Constant.CLN_MODIFY_TIME);
		boolean hasSpceCln = columns.stream().anyMatch(cln -> specs.contains(cln.getName()));
		boolean hasText = columns.stream().anyMatch(cln -> {
			ClnType clnType = ClnType.find(cln.getType());
			return clnType == ClnType.TEXT || clnType == ClnType.BLOB;
		});
		String back = builder.toString();
		if (back.startsWith(",")) {
			back = back.substring(1);
			back = "showFlags: '" + back + "', " + (hasSpceCln ? "showDefault: false, " : "");
		} else {
			back = hasSpceCln ? "showDefault: false, " : "";
		}
		return back + (hasText ? "showText: true, " : "");
	}

	private String removeLine(String fileTxt, int tab, String line) {
		int start = fileTxt.indexOf(tabStr(tab) + line);
		if (start > 0) {
			String temp = fileTxt.substring(start);
			temp = temp.substring(0, temp.indexOf("\n") + 1);
			return fileTxt.replace(temp, "");
		}
		return fileTxt;
	}

	public String tabStr(int tab) {
		if (tab <= 0) return "";
		StringBuilder buffer = new StringBuilder();
		for (int i = 1; i <= tab; i++) {
			buffer.append("  ");
		}
		return buffer.toString();
	}

	// 获取查询表单
	public static String getFormItem(Table table, Column cln, String priKey, int tab, boolean isSave) {
		StrBuf formShemas = new StrBuf(true);
		String clnCmmt = getCmmt(cln, "").replace("ID集", "")
				.replace("ID集合", "列表").replaceAll("\\[.*\\]", "");
		ClnType clnType = ClnType.find(cln.getType());
		String clnName = AutoUtil.firstLowerBean(cln.getName());
		FormType formType = FormType.find(cln.getFormType());
		String linkShowCln = cln.getLinkTable() == null ? "" : cln.getLinkTable().getShowCln();
		boolean isArray = clnName.endsWith("s") && (cln.getCmmt().endsWith("集合") || cln.getCmmt().endsWith("集"));

		// 特定固定字段
		if (cln.getName().equals(Constant.ID_NAME)) {
			formShemas.append(tab + 1, "api.getSchema('id'),");
			return formShemas.moveLast().toString();
		} else if (cln.getName().equals(Constant.CLN_CREATE_BY)) {
			formShemas.append(tab + 1, "api.getSchema('createBy'),");
			return formShemas.moveLast().toString();
		} else if (cln.getName().equals(Constant.CLN_MODIFY_BY)) {
			formShemas.append(tab + 1, "api.getSchema('updateBy'),");
			return formShemas.moveLast().toString();
		} else if (cln.getName().equals(Constant.CLN_CREATE_TIME)) {
			formShemas.append(tab + 1, "api.getSchema('createTime'),");
			return formShemas.moveLast().toString();
		} else if (cln.getName().equals(Constant.CLN_MODIFY_TIME)) {
			formShemas.append(tab + 1, "api.getSchema('updateTime'),");
			return formShemas.moveLast().toString();
		} else if (cln.getName().equals(Constant.CLN_STATUS) && StatusEnum.is(cln.getLimits())) {
			// 正常、删除状态不显示
			formShemas.append(tab + 1, "api.getSchema('status'),");
			return formShemas.moveLast().toString();
		} else if (cln.getName().equals(Constant.CLN_STATUS) && ShowStatus.is(cln.getLimits())) {
			formShemas.append(tab + 1, "api.getSchema('showStatus'),");
			return formShemas.moveLast().toString();
		} else if (cln.getName().equals(Constant.CLN_STATUS) && ShowStrStatus.is(cln.getLimits())) {
			formShemas.append(tab + 1, "api.getSchema('showStrStatus'),");
			return formShemas.moveLast().toString();
		}
		// 表单隐藏字段[简化处理]
		if ((!isTrue(cln.getFormShow()) && (clnType == ClnType.BOOLEAN || clnType == ClnType.DATE
				|| clnType == ClnType.DATETIME || cln.isNumber() || cln.isDecimal()
				|| formType != FormType.RICH_TEXT)) || !isTrue(table.getHasAction())) {
			if (clnName.equals(Constant.CLN_STATUS) && StatusEnum.is(cln.getLimits())) {
				return "";
			}
			// 'number' | 'string' | 'boolean' | 'date' | 'time' | 'text' | 'select' | 'status'
			String type = cln.isNumber() || cln.isDecimal() ? "number" : "string";
			if (clnType == ClnType.DATE) type = "date";
			if (clnType == ClnType.DATETIME) type = "time";
			if (isShowInDetail(cln, clnType, formType)) type = "text";
			if (Entity.hasLimits(cln.getLimits())) type = "select";
			// 表格编辑不显示
			boolean editShow = !isTrue(cln.getListShow()) || !isTrue(cln.getFormShow());
			// 表格不显示
			boolean tableShow = true;
			if (!isTrue(cln.getListShow()) || ColumnTypeEnum.find(cln.getType()) == ColumnTypeEnum.Text
					|| ColumnTypeEnum.find(cln.getType()) == ColumnTypeEnum.Blob) {
				tableShow = false;
			}
			if (cln.getLinkTable() != null && !Constant.NEW_TENANT_ID.equals(clnName)) {
				String name = cln.getName().replace("_ids", "_list").replace("_id", "");
				if (cln.getName().contains("_ids")) {
					clnName = AutoUtil.firstLowerBean(name) + "Text";
				} else {
					clnName = AutoUtil.firstLowerBean(name) + "." + cln.getLinkTable().getShowCln();
				}
			}
			int width = getTableWidth(cln, priKey, clnType, formType);
			if (type.equals("select")) {
				int colSpan = table.getRowCol() != null && table.getRowCol() == 2 ? 12 : 24;
				String options = "[\n" + getLimitsHtml(clnName, cln.getLimits(), 3) + "    ]";
				formShemas.append(tab + 1, "api.formHideSchema('{1}', '{2}', '{3}', {4}, {5}, {6}, {7}, {8}, {9}, '{3}Text'),", type,
						clnCmmt, clnName, editShow, tableShow, width, colSpan, getLimitsFirstValue(clnName, cln.getLimits()), options);
			} else if (table.getRowCol() != null && table.getRowCol() == 2 && !isShowInDetail(cln, clnType, formType)
					&& isTrue(cln.getFormShow())) {
				formShemas.append(tab + 1, "api.formHideSchema('{1}', '{2}', '{3}', {4}, {5}, {6}, 12),", type,
						clnCmmt, clnName, editShow, tableShow, width);
			} else {
				formShemas.append(tab + 1, "api.formHideSchema('{1}', '{2}', '{3}', {4}, {5}, {6}),", type,
						clnCmmt, clnName, editShow, tableShow, width);
			}
			return formShemas.moveLast().toString();
		}

		// formShemas.append(tab + 1, "{");
		formShemas.append(tab + 2, "label: '{1}',", clnCmmt);
		formShemas.append(tab + 2, "field: '{1}',", clnName);
		if (!isSave) {
			return formShemas.moveLast().toString();
		}
		/*if (isTrue(cln.getFormShow())) {
			formShemas.append(tab + 2, "editRow: true,");
			// 编辑必填
			if (isTrue(cln.getRequired())) {
				formShemas.append(tab + 2, "editRule: true,");
			}
		}*/
		// 必填
		if (isTrue(cln.getFormShow()) && isTrue(cln.getRequired())) {
			formShemas.append(tab + 2, "required: true,");
		}
		// 表单不显示
		if (!isTrue(cln.getFormShow())) {
			formShemas.append(tab + 2, "formShow: false,");
		}
		// 表单属性[搜索需要，所有字段都显示，除非表格和表单都不显示]
		if (cln.getFormShow()) {
			if (clnType == ClnType.BOOLEAN) {
				formShemas.append(tab + 2, "component: 'RadioButtonGroup',");
				formShemas.append(tab + 2, "componentProps: {");
				formShemas.append(tab + 3, "options: [");
				formShemas.append(tab + 4, "{ label: '否', value: false },");
				formShemas.append(tab + 4, "{ label: '是', value: true }");
				formShemas.append(tab + 3, "]");
				formShemas.append(tab + 2, "},");
			}
			else if (Entity.hasLimits(cln.getLimits())) { // && !cln.getName().equals(Constant.CLN_STATUS)
				formShemas.append(tab + 2, "component: 'Select',");
				formShemas.append(tab + 2, "componentProps: {");
				formShemas.append(tab + 3, "options: [");
				formShemas.append(getLimitsHtml(clnName, cln.getLimits(), tab + 4));
				formShemas.append(tab + 3, "],");
				if (getDefaultValue(cln, clnType) != null) {
					formShemas.append(tab + 3, getDefaultValue(cln, clnType));
				}
				formShemas.append(tab + 2, "},");
			}
			else if (formType == FormType.IMAGE || formType == FormType.FILE) {
				formShemas.append(tab + 2, "component: '{1}',", formType == FormType.IMAGE ? "ImageUpload" : "FileUpload");
				formShemas.append(tab + 2, "componentProps: {");
				//formShemas.append(tab + 3, "api: api.uploadApi,");
				if (isArray) {
					formShemas.append(tab + 3, "maxNumber: 3,");
				} else {
					//formShemas.append(tab + 3, "maxNumber: 1,");
					formShemas.append(tab + 3, "string: true,");
				}
				formShemas.append(tab + 2, "},");
			}
			else if (clnType == ClnType.DATE) {
				formShemas.append(tab + 2, "component: 'DatePicker',");
				formShemas.append(tab + 2, "componentProps: api.getDateProp('date'),");
				formShemas.append(tab + 2, "customRender: ({ value }) => api.parseDate(value),");
			}
			else if (clnType == ClnType.DATETIME) {
				formShemas.append(tab + 2, "component: 'DatePicker',");
				formShemas.append(tab + 2, "componentProps: api.getDateProp('time'),");
				formShemas.append(tab + 2, "customRender: ({ value }) => api.parseMinute(value),");
			}
			// 级联查找 [getData.params]
			else if (formType == FormType.SELECT) { // || formType == FormType.MY_CONF
				if (cln.getLinkTable() == null || cln.getLinkTable().getModule() == null) {
					System.out.println("表字段" + cln.getName() + "需要配置链接类！");
					throw new MsgException("表字段" + cln.getName() + "需要配置链接类！");
				}
				String moduleName = cln.getLinkTable().getModule().getName();
				if (moduleName.contains("/")) {
					moduleName = moduleName.substring(moduleName.indexOf("/") + 1);
				}
				if (cln.getLinkTable().getIsTree()) {
					formShemas.append(tab + 2, "component: 'ApiCascader',");
					formShemas.append(tab + 2, "componentProps: {");
					formShemas.append(tab + 3, "api: async (params) => await api.offsetBy('{1}.{2}'," +
							" { showFields: 'id,{3}', showFlags: 'children[id,{3}]', params: { pid: 0, ...params } }),"
							, moduleName, AutoUtil.firstLowerBean(cln.getLinkTable().getName()), linkShowCln);
					formShemas.append(tab + 3, "labelField: '{1}',", linkShowCln);
					formShemas.append(tab + 3, "valueField: 'id',");
					formShemas.append(tab + 3, "apiParamKey: 'pid',");
					formShemas.append(tab + 3, "isLeaf: (arg) => !arg.children,");
					formShemas.append(tab + 2, "},");
				} else {
					formShemas.append(tab + 2, "component: 'ApiSelect',");
					formShemas.append(tab + 2, "componentProps: {");
					formShemas.append(tab + 3, "api: async (params) => await api.offsetBy('{1}.{2}'," +
									" { showFields: 'id,{3}', params }),"
							, moduleName, AutoUtil.firstLowerBean(cln.getLinkTable().getName()), linkShowCln);
					formShemas.append(tab + 3, "labelField: '{1}',", linkShowCln);
					formShemas.append(tab + 3, "valueField: 'id',");
					if (cln.getName().endsWith("_ids")) {
						formShemas.append(tab + 3, "mode: 'multiple',");
					}
					formShemas.append(tab + 2, "},");
				}
			}
			// 父ID
			else if (clnName.equals("pid")) {
				formShemas.append(tab + 2, "component: 'ApiTreeSelect',");
				formShemas.append(tab + 2, "componentProps: {");
				formShemas.append(tab + 3, "api: async (params) => await api.offsetBy(bean," +
								" { pageSize: 1000, showFields: 'id,name', showFlags: 'children', orderBy: 'id$asc', params: { pid: 0 } }),");
				formShemas.append(tab + 3, "labelField: '{1}',", table.getShowCln());
				formShemas.append(tab + 3, "valueField: 'id',");
				formShemas.append(tab + 2, "},");
				formShemas.append(tab + 2, "tableShow: false,");
			}
			else if (cln.isNumber() || cln.isDecimal()) {
				formShemas.append(tab + 2, "component: 'InputNumber',");
				if (isTrue(cln.getUnsigned())) {
					formShemas.append(tab + 2, "componentProps: { min: 0 },");
				}
			}
			// 富媒体
			else if (formType == FormType.RICH_TEXT) {
				formShemas.append(tab + 2, "component: 'InputTextArea',");
				formShemas.append(tab + 2, "render: ({ model, field }) => {");
				formShemas.append(tab + 3, "return h(Tinymce, {");
				formShemas.append(tab + 4, "value: model[field],");
				formShemas.append(tab + 4, "onChange: (value: string) => {");
				formShemas.append(tab + 5, "model[field] = value;");
				formShemas.append(tab + 4, "}");
				formShemas.append(tab + 3, "});");
				formShemas.append(tab + 2, "},");
			}
			else if (isShowInDetail(cln, clnType, formType)) {
				formShemas.append(tab + 2, "component: 'InputTextArea',");
			}
			else if (isTrue(cln.getFormShow())) {
				formShemas.append(tab + 2, "component: 'Input',");
			}
		}
		String cValue = isArray ? "record."+clnName+" || []" : "record."+clnName+" ? [record."+clnName+"] : []";
		if (clnType == ClnType.BOOLEAN) {
			formShemas.append(tab + 2, "customRender: ({ value }) => {");
			// formShemas.append(tab + 3, "return h(Tag, { color: value ? 'green' : 'red' }, value ? '是' : '否')");
			formShemas.append(tab + 3, "return h('span', { style: value ? 'color:green;'" +
					" : 'color:red;' }, value ? '是' : '否');");
			formShemas.append(tab + 2, "},");
		}
		else if (formType == FormType.IMAGE) {
			formShemas.append(tab + 2, "customRender: ({ record }) => h(TableImg, { imgList: {1} }),", cValue);
			//formShemas.append(tab + 3, "return h(TableImg, { imgList: {1}, simpleShow: true, size: 55 })", cValue);
			//formShemas.append(tab + 2, "},");
		}
		else if (formType == FormType.FILE) {
			formShemas.append(tab + 2, "customRender: ({ record }) => h(FileUpload, { value: {1}, disabled: true }),", cValue);
		}
		// 级联查找
//		else if (formType == FormType.SELECT) {
//			formShemas.append(tab + 2, "customRender:({ record }) => record?.{1}?.{2} ?? record?.{3},",
//					AutoUtil.firstLowerBean(cln.getName().replace("_id", "")), linkShowCln, clnName);
//			//TODO editRender: ({ record }) => record?.implPhase?.name ?? record?.implPhaseId,
//		}

		String defaultValue = getDefaultValue(cln, clnType);
		if (StrUtil.isNotEmpty(defaultValue) && isTrue(cln.getFormShow())) {
			formShemas.append(tab + 2, defaultValue);
		}
		if (table.getRowCol() != null && table.getRowCol() == 2 && !isShowInDetail(cln, clnType, formType)
				&& isTrue(cln.getFormShow())) {
			formShemas.append(tab + 2, "colProps: { span: 12 },");
		}
		// 是否溢出缩短显示
		if (isTrue(cln.getOverflow())) {
			formShemas.append(tab + 2, "ellipsis: true,");
		}
		// 是否靠左侧显示[多行文本]
		if (isShowInDetail(cln, clnType, formType) && !(formType == FormType.IMAGE || formType == FormType.FILE)) {
			formShemas.append(tab + 2, "align: 'left',");
		}
		// 自增ID长度80
		int width = getTableWidth(cln, priKey, clnType, formType);
		if (width > 0) {
			formShemas.append(tab + 2, "width: {1},", width);
		}
		return formShemas.moveLast().toString();
	}

	private static int getTableWidth(Column cln, String priKey, ClnType clnType, FormType formType) {
		if (!isTrue(cln.getListShow())) return 0;
		if (priKey.equals(cln.getName())) {
			return 80;
		}
		if (cln.getListWidth() != null && cln.getListWidth() > 0) {
			return cln.getListWidth();
		}
		if (clnType == ClnType.BOOLEAN) {
			return 80;
		}
		else if (!StrUtil.isEmpty(cln.getLimits())) { // && !cln.getName().equals(Constant.CLN_STATUS)
			return 110;
		}
		else if (formType == FormType.IMAGE || formType == FormType.FILE) {
			return formType == FormType.IMAGE ? 90 : 180;
		}
		else if (clnType == ClnType.DATE || clnType == ClnType.DATETIME) {
			return clnType == ClnType.DATE ? 138 : 150;
		}
		else if (cln.isNumber() || cln.isDecimal()) {
			return 130;
		}
		return 0;
	}

	private static String getDefaultValue(Column cln, ClnType clnType) {
//		if (!isTrue(cln.getNotNull()) && cln.getDefVal() != null && StrUtil.isNotEmpty(cln.getDefVal())
//				&& !cln.getDefVal().equals("NULL") && !isTrue(cln.getRequired())) {
		if (cln.getDefVal() != null && StrUtil.isNotEmpty(cln.getDefVal()) && !cln.getDefVal().equals("NULL")
				&& !cln.getDefVal().equals("NOW")) {
			if (clnType == ClnType.BOOLEAN) {
				return StrBuf.format("defaultValue: {1},", cln.getDefVal().equals("1"));
			} else if (cln.isNumber() || cln.isDecimal()) {
				return StrBuf.format("defaultValue: {1},", cln.getDefVal());
			} else {
				return StrBuf.format("defaultValue: '{1}',", cln.getDefVal().equals("空") ? "" : cln.getDefVal());
			}
		}
		return null;
	}

	// 获取查询表单
	public static String getCrudSchemas(Table table, List<Column> columns, int tab) {
		String priKey = getPriKeyClnName(columns);
		StrBuf crudSchemas = new StrBuf(true);
		for (Column cln : columns) {
			String clnName = AutoUtil.firstLowerBean(cln.getName());

			// 表格和输入都不显示不输出
			if (!isTrue(cln.getFormShow()) && !isTrue(cln.getListShow())) {
				continue;
			}

			String formItem = getFormItem(table, cln, priKey, tab, true);
			if (!formItem.contains("api.getSchema(") && !formItem.contains("api.formHideSchema(") && StrUtil.isNotEmpty(formItem)) {
				crudSchemas.append(tab + 1, "{");
			}
			if (StrUtil.isNotEmpty(formItem)) {
				crudSchemas.append(formItem + "\n");
			}
			if (!formItem.contains("api.getSchema(") && !formItem.contains("api.formHideSchema(") && StrUtil.isNotEmpty(formItem)) {
				// 表格不显示
				if (!isTrue(cln.getListShow()) || ColumnTypeEnum.find(cln.getType()) == ColumnTypeEnum.Text
						|| ColumnTypeEnum.find(cln.getType()) == ColumnTypeEnum.Blob || cln.getLength() >= 2048) {
					crudSchemas.append(tab + 2, "tableShow: false,");
				} else if (StrUtil.isNotEmpty(cln.getLimits())) {
					crudSchemas.append(tab + 2, "dataIndex: '{1}Text',", clnName);
				} else if (cln.getLinkTable() != null && !Constant.NEW_TENANT_ID.equals(clnName)) {
					String name = cln.getName().replace("_ids", "_list").replace("_id", "");
					if (cln.getName().contains("_ids")) {
						crudSchemas.append(tab + 2, "dataIndex: '{1}Text',", AutoUtil.firstLowerBean(name));
					} else {
						crudSchemas.append(tab + 2, "dataIndex: ['{1}', '{2}'],", AutoUtil.firstLowerBean(name), cln.getLinkTable().getShowCln());
					}
				} else if (clnName.endsWith("s") && (cln.getCmmt().endsWith("集合") || cln.getCmmt().endsWith("集"))) {
					crudSchemas.append(tab + 2, "dataIndex: '{1}Text',", clnName);
				}
				crudSchemas.append(tab + 1, "},");
			}
		}
		return crudSchemas.moveLast().toString();
	}

	private static boolean isShowInDetail(Column cln, ClnType clnType, FormType formType) {
		return clnType == ClnType.TEXT || clnType == ClnType.BLOB || formType == FormType.MUL_INPUT || cln.getLength() > 255; //cln.getLength() >= 1024
	}

	// 限制html
	private static String getLimitsHtml(String clnName, String limitStr, int tab) {
		Limits limits = new Limits(limitStr);
		StrBuf result = new StrBuf(true);
		for (Limits.Dict dict : limits.getDictList()) {
			String prev = dict.getIntKey() == null ? dict.getStrKey() : dict.getIntKey() + "";
			String next = dict.getValue();
			if (clnName.equals("status") && (prev.equals("DELETE") || prev.equals("0"))) {
				continue;
			}
			if (dict.getIntKey() == null) {
				result.append(tab,"{ label: '{1}', value: '{2}' },", next, prev);
			} else {
				result.append(tab,"{ label: '{1}', value: {2} },", next, prev);
			}
		}
		return result.toString();
	}

	// 限制html
	private static String getLimitsFirstValue(String clnName, String limitStr) {
		Limits limits = new Limits(limitStr);
		StrBuf result = new StrBuf(true);
		for (Limits.Dict dict : limits.getDictList()) {
			String prev = dict.getIntKey() == null ? dict.getStrKey() : dict.getIntKey() + "";
			if (clnName.equals("status") && (prev.equals("DELETE") || prev.equals("0"))) {
				continue;
			}
			return "'" + prev + "'";
		}
		return result.toString();
	}

	public static String fillByKey(String fileTxt, String start, String end, String value) {
		int startIndex = fileTxt.indexOf(start);
		if (startIndex > -1) {
			String temp = fileTxt.substring(startIndex);
			int endIndex = temp.indexOf(end);
			if (endIndex > -1) {
				temp = temp.substring(0, endIndex);
				fileTxt = fileTxt.replace(temp, start + "\n" + value + "\n");
			}
		}
		return fileTxt;
	}

	public static String getCmmt(Column cln, String last) {
		String comment = cln.getCmmt().replaceAll("\\[.*\\]", "");
		if (last != null && cln.getLinkTable() != null && comment.endsWith("ID")) {
			return comment.substring(0, comment.length() - 2) + last;
		}
		return comment;
	}
}
